package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.utils.StringUtils;
import com.tanhua.commons.templates.AipFaceTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.vo.ErrorResult;
import com.tanhua.domain.vo.UserInfoVo;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserService {

    @Reference
    private UserApi userApi;
    @Reference
    private UserInfoApi userInfoApi;

    @Autowired
    private SmsTemplate smsTemplate;
    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private AipFaceTemplate aipFaceTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    // 定义redis中存储的验证码的key的前缀
    private static final String SMS_KEY = "SMS_KEY_";
    // 定义redis中存储的token的key的前缀
    private final String TOKEN_KEY = "TOKEN_KEY_";
    // 获取密钥
    @Value("${tanhua.secret}")
    private String secret;

    /**
     * 保存用户
     * 参数如果是json格式传递，那么我们接收参数需要添加
     *
     * @return 新增用户的主键
     */
    @PostMapping("/save")
    public ResponseEntity save(@RequestBody User user) {
        Long id = userApi.save(user);
        return ResponseEntity.ok(id);
    }


    /**
     * 根据手机号查找用户
     */
    public ResponseEntity findByMobile(String mobile) {
        try {
            int i = 1 / 0;
            User user = userApi.findByMobile(mobile);
            return ResponseEntity.ok(user);
        } catch (Exception e) {
            e.printStackTrace();
            Map<String, String> resultMap = new HashMap<>();
            resultMap.put("errCode", "110");
            resultMap.put("errMsg", "系统正在升级中，请稍后！");
            return ResponseEntity.status(500).body(resultMap);
        }
    }

    /**
     * 发送验证码短信
     *
     * @param phone 手机号
     * @return
     */
    public ResponseEntity sendSms(String phone) {
        //1. 生成6位验证码  ,这里的验证码我就写死了。
        String code = (int) ((Math.random() * 9 + 1) * 100000) + "";
        code = "123456";

        //3. 把验证码存储到redis中,key是: SMS_KEY_ + 手机号; 有效时间5分钟
        redisTemplate.opsForValue().set(SMS_KEY + phone, code, Duration.ofMinutes(5));
        //4. 返回响应
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：登录第二步---验证码校验
     */
    public ResponseEntity<Object> loginVerification(String phone, String verificationCode) {
        // 1.从redis中获取验证码并校验验证码
        String redisCode = redisTemplate.opsForValue().get(SMS_KEY + phone);
        if (redisCode == null || !redisCode.equals(verificationCode)) {
            return ResponseEntity.status(401).body(ErrorResult.loginError());
        }
        // 2.校验完毕，从redis中删除验证码
        redisTemplate.delete(SMS_KEY + phone);
        // 3.根据手机号码查询用户
        User user = userApi.findByMobile(phone);
        boolean isNew = false;
        // 3.1 判断如果用户不存在，自动注册
        if (user == null) {
            user = new User();
            user.setMobile(phone);
            // md5加密
            user.setPassword(DigestUtils.md5Hex("123456"));
            // 添加用户【获取返回的id】
            Long userId = userApi.save(user);
            // 设置用户id（后面对象转json必须要带上用户id）
            user.setId(userId);
            isNew = true;
        }
        // 【生成token、存储token到redis中】
        String token = JwtUtils.createToken(user.getId(), phone, secret);
        // 【往token中存储的应该是整个用户对象数据，所以这里需要把对象转换为json字符串存储】
        String tokenData = JSON.toJSONString(user);
        // 【生成的token作为key，用户数据作为value，存储到redis中，并设置过期时间】
        redisTemplate.opsForValue().set(TOKEN_KEY + token, tokenData, Duration.ofHours(4));
        // 4.构造返回结果
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("isNew", isNew);
        // 【设置响应的数据中包含token，满足需求】
        resultMap.put("token", token);

        return ResponseEntity.ok(resultMap);
    }

    /**
     * 接口名称：新用户---1填写资料
     * 需求描述：用户第一次登陆，需要完善用户信息
     */
    public ResponseEntity<Object> saveUserInfo(UserInfo userInfo) {
        User user = UserHolder.get();

        // 设置用户详情id
        userInfo.setId(user.getId());
        // 保存
        // 下一章实现
        userInfoApi.save(userInfo);
        return ResponseEntity.ok(null);
    }

    /**
     * 根据token查找用户
     */
    public User findUserByToken(String token) {
        // 根据token，获取用户信息（json字符串）
        String userJsonString = redisTemplate.opsForValue().get(TOKEN_KEY + token);
        if (StringUtils.isEmpty(userJsonString)) {
            return null;
        }
        // 把json字符串转换为对象
        User user = JSON.parseObject(userJsonString, User.class);
        // 更新token有效时间
        redisTemplate.opsForValue().set(TOKEN_KEY + token, userJsonString, Duration.ofHours(4));
        return user;
    }

    /**
     * 完善用户信息 - 上传用户头像
     */
    public ResponseEntity<Object> updateUserHead(MultipartFile headPhoto) throws IOException {
        // 1.根据token获取用户
        User user = UserHolder.get();

        // 2.检测图片是否包含人脸
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect) {
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }
        // 3.图片上传到阿里云OSS
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());
        // 4.更新UserInfo，修改用户头像地址信息
        UserInfo info = new UserInfo();
        info.setId(user.getId());
        info.setAvatar(url);
        userInfoApi.update(info);
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：用户资料 - 读取
     *
     * @param
     * @return
     */
    public ResponseEntity<Object> findUserInfoById() {
        // 从当前线程上直接获取用户id（拦截器已经处理）
        Long userId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(userInfo, userInfoVo);
        if (userInfo.getAge() != null) {
            userInfoVo.setAge(userInfo.getAge().toString());
        }
        return ResponseEntity.ok(userInfoVo);
    }

    /**
     * 接口名称：用户资料 - 保存
     */
    public ResponseEntity<Object> updateUserInfo(UserInfo userInfo) {
        // 1.根据token获取用户
        User user = UserHolder.get();
        // 2.设置用户明细中用户的id（请求中没有id参数）
        userInfo.setId(user.getId());
        // 3.修改用户信息
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    /**
     * 修改手机号 - 2 校验验证码
     */

    public ResponseEntity<Object> checkCode(String verificationCode) {
        // 1.获取用户信息
        User user = UserHolder.get();
        String phone = user.getMobile();
        Map<String, Object> resultMap = new HashMap<>();
        // 2.判断
        String redisCode = redisTemplate.opsForValue().get(SMS_KEY + phone);
        if (redisCode == null || !redisCode.equals(verificationCode)) {
            //校验失败
            resultMap.put("verification", false);
            return ResponseEntity.ok(resultMap);
        }
        redisTemplate.delete(SMS_KEY + phone);
        resultMap.put("verification", true);
        return ResponseEntity.ok(resultMap);
    }

    /**
     * 修改手机号 - 3 保存
     *
     * @param phone 修改后的手机号
     * @return
     */
    public ResponseEntity<Object> updatePhone(String phone) {
        // 1.根据修改后的手机号码查询，如果手机号码已经存在返回错误信息
        User user = userApi.findByMobile(phone);
        if (user != null) {
            return ResponseEntity.status(500).body(ErrorResult.mobileError());
        }
        // 2.获取用户信息、设置修改手机号
        User updateUser = UserHolder.get();
        updateUser.setMobile(phone);
        // 3.修改用户
        userApi.updatePhone(updateUser);
        return ResponseEntity.ok(null);
    }
}
